/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | foam-extend: Open Source CFD
   \\    /   O peration     | Version:     4.1
    \\  /    A nd           | Web:         http://www.foam-extend.org
     \\/     M anipulation  | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
	This file is part of foam-extend.

	foam-extend is free software: you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the
	Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	foam-extend is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.

Class
	Foam::coupledPolyPatch

Description
	The coupledPolyPatch is an abstract base class for patches that couple
	regions of the computational domain e.g. cyclic and processor-processor
	links.

SourceFiles
	coupledPolyPatch.C
	coupledPolyPatchMorph.C

\*---------------------------------------------------------------------------*/

#ifndef coupledPolyPatch_H
#define coupledPolyPatch_H

#include "polyPatch.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{


class coupledPolyPatch
:
	public polyPatch
{
protected:

	// Protected data

		// Alowing derived classes to create their own transformation
		// HJ, 24/Oct/2008

		//- Offset (distance) vector from one side of the couple to the other
		mutable vectorField separation_;

		//- Face transformation tensor
		mutable tensorField forwardT_;

		//- Neighbour-cell transformation tensor
		mutable tensorField reverseT_;


	// Protected Member Functions

		//- Calculate the transformation tensors
		//  smallDist : matching distance per face
		//  absTol    : absolute error in normal
		void calcTransformTensors
		(
			const vectorField& Cf,
			const vectorField& Cr,
			const vectorField& nf,
			const vectorField& nr,
			const scalarField& smallDist,
			const scalar absTol = matchTol_()
		) const;

		//- Initialise the calculation of the patch addressing
		virtual void initAddressing() = 0;

		//- Calculate the patch addressing
		virtual void calcAddressing() = 0;

		//- Initialise the calculation of the patch geometry
		virtual void initGeometry() = 0;

		//- Calculate the patch geometry
		virtual void calcGeometry() = 0;

		//- Initialise the patches for moving points
		virtual void initMovePoints(const pointField&) = 0;

		//- Correct patches after moving points
		virtual void movePoints(const pointField&) = 0;


public:

	//- Runtime type information
	TypeName("coupled");


	// Constructors

		//- Construct from components
		coupledPolyPatch
		(
			const word& name,
			const label size,
			const label start,
			const label index,
			const polyBoundaryMesh& bm
		);

		//- Construct from dictionary
		coupledPolyPatch
		(
			const word& name,
			const dictionary& dict,
			const label index,
			const polyBoundaryMesh& bm
		);

		//- Construct as copy
		coupledPolyPatch(const coupledPolyPatch&);

		//- Construct as copy, resetting the boundary mesh
		coupledPolyPatch(const coupledPolyPatch&, const polyBoundaryMesh&);

		//- Construct given the original patch and resetting the
		//  face list and boundary mesh information
		coupledPolyPatch
		(
			const coupledPolyPatch& pp,
			const polyBoundaryMesh& bm,
			const label index,
			const label newSize,
			const label newStart
		);


	//- Destructor
	virtual ~coupledPolyPatch();


	// Member Functions

		// Access

			//- Return true if patch is coupled
			virtual bool coupled() const
			{
				return true;
			}

			//- Does this side own the patch ?
			virtual bool master() const = 0;

			//- Does the coupled side own the patch ?
			virtual bool slave() const
			{
				return !master();
			}


			//- Are the coupled planes separated
			bool separated() const
			{
				return separation_.size();
			}

			//- Return the offset (distance) vector from one side of the couple
			//  to the other
			const vectorField& separation() const
			{
				return separation_;
			}


			//- Are the cyclic planes parallel
			bool parallel() const
			{
				return forwardT_.empty();
			}

			//- Return face transformation tensor
			const tensorField& forwardT() const
			{
				return forwardT_;
			}

			//- Return neighbour-cell transformation tensor
			const tensorField& reverseT() const
			{
				return reverseT_;
			}


		//- Initialize ordering for primitivePatch. Does not
		//  refer to *this (except for name() and type() etc.)
		virtual void initOrder(const primitivePatch&) const = 0;

		//- Return new ordering for primitivePatch.
		//  Ordering is -faceMap: for every face
		//  index of the new face -rotation:for every new face the clockwise
		//  shift of the original face. Return false if nothing changes
		//  (faceMap is identity, rotation is 0), true otherwise.
		virtual bool order
		(
			const primitivePatch&,
			labelList& faceMap,
			labelList& rotation
		) const = 0;

		//- Synchronise communications of ordering for primitivePatch
		//  Used in cases when no topological change happens locally,
		//  but is happening on other processors
		virtual void syncOrder() const = 0;
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
